package health_system.health_system.repository;

import health_system.health_system.entity.Moment;
import health_system.health_system.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
public interface MomentRepository extends JpaRepository<Moment, Long> {
    
    // Find moments by user
    List<Moment> findByUserOrderByCreatedAtDesc(User user);
    
    // Find moments by user with pagination
    Page<Moment> findByUserOrderByCreatedAtDesc(User user, Pageable pageable);
    
    // Find moments visible to a specific user (based on privacy settings)
    @Query("SELECT m FROM Moment m WHERE " +
           // Public moments
           "(m.visibility = 'PUBLIC') OR " +
           // User's own moments
           "(m.user = :viewer) OR " +
           // Only friends can see
           "(m.visibility = 'FRIENDS' AND " +
           "EXISTS (SELECT f FROM Friendship f WHERE " +
           "((f.requester = m.user AND f.addressee = :viewer) OR " +
           "(f.requester = :viewer AND f.addressee = m.user)) AND f.status = 'ACCEPTED')) OR " +
           // Custom visibility
           "(m.visibility = 'CUSTOM' AND :viewer MEMBER OF m.visibleToUsers) " +
           "ORDER BY m.createdAt DESC")
    List<Moment> findMomentsVisibleToUser(@Param("viewer") User viewer);
    
    // Find moments with pagination and time-based filtering
    @Query("SELECT m FROM Moment m WHERE " +
           // Public moments
           "(m.visibility = 'PUBLIC') OR " +
           // User's own moments
           "(m.user = :viewer) OR " +
           // Only friends can see
           "(m.visibility = 'FRIENDS' AND " +
           "EXISTS (SELECT f FROM Friendship f WHERE " +
           "((f.requester = m.user AND f.addressee = :viewer) OR " +
           "(f.requester = :viewer AND f.addressee = m.user)) AND f.status = 'ACCEPTED')) OR " +
           // Custom visibility
           "(m.visibility = 'CUSTOM' AND :viewer MEMBER OF m.visibleToUsers) " +
           "AND (m.visibilityDuration = 0 OR m.createdAt >= :since) " +
           "ORDER BY m.createdAt DESC")
    Page<Moment> findVisibleMomentsCreatedSince(@Param("viewer") User viewer, 
                                               @Param("since") LocalDateTime since,
                                               Pageable pageable);
    
    // Find moments for timeline with recommendation algorithm factors
    @Query("SELECT m FROM Moment m WHERE " +
           "(" +
           // Standard visibility filters
           "(m.visibility = 'PUBLIC') OR " +
           "(m.user = :viewer) OR " +
           "(m.visibility = 'FRIENDS' AND " +
           "EXISTS (SELECT f FROM Friendship f WHERE " +
           "((f.requester = m.user AND f.addressee = :viewer) OR " +
           "(f.requester = :viewer AND f.addressee = m.user)) AND f.status = 'ACCEPTED')) OR " +
           "(m.visibility = 'CUSTOM' AND :viewer MEMBER OF m.visibleToUsers)" +
           ") " +
           "ORDER BY " +
           // Ordering factors for recommendation (simplified)
           "CASE WHEN EXISTS (SELECT f FROM Friendship f WHERE " +
           "((f.requester = m.user AND f.addressee = :viewer) OR " +
           "(f.requester = :viewer AND f.addressee = m.user)) AND f.status = 'ACCEPTED') THEN 1 ELSE 0 END DESC, " +
           "m.createdAt DESC")
    Page<Moment> findRecommendedMomentsForUser(@Param("viewer") User viewer, Pageable pageable);
    
    // Find moments by time range for privacy settings (three days, one month, half year)
    @Query("SELECT m FROM Moment m WHERE m.user = :user AND " +
           "m.createdAt BETWEEN :startDate AND :endDate ORDER BY m.createdAt DESC")
    List<Moment> findByUserAndDateRange(@Param("user") User user, 
                                      @Param("startDate") LocalDateTime startDate, 
                                      @Param("endDate") LocalDateTime endDate);
    
    // Count user's moments
    Long countByUser(User user);
    
    // Find moments with specific keywords
    @Query("SELECT m FROM Moment m WHERE " +
           "(m.content LIKE %:keyword%) AND " +
           // Apply visibility filters
           "(" +
           "(m.visibility = 'PUBLIC') OR " +
           "(m.user = :viewer) OR " +
           "(m.visibility = 'FRIENDS' AND " +
           "EXISTS (SELECT f FROM Friendship f WHERE " +
           "((f.requester = m.user AND f.addressee = :viewer) OR " +
           "(f.requester = :viewer AND f.addressee = m.user)) AND f.status = 'ACCEPTED')) OR " +
           "(m.visibility = 'CUSTOM' AND :viewer MEMBER OF m.visibleToUsers)" +
           ") " +
           "ORDER BY m.createdAt DESC")
    List<Moment> searchMomentsByKeyword(@Param("keyword") String keyword, @Param("viewer") User viewer);
} 